package cn.hengzhu.main_manager.web.controller;

import cn.hengzhu.main_manager.repository.dao.*;
import cn.hengzhu.main_manager.repository.domain.*;
import cn.hengzhu.main_manager.repository.param.CompBillParam;
import cn.hengzhu.main_manager.repository.vo.CompBillListVO;
import cn.hengzhu.main_manager.repository.vo.CompBillVO;
import cn.hengzhu.main_manager.repository.vo.CompVO;
import cn.hengzhu.main_manager.utils.AjaxResult;
import cn.hengzhu.main_manager.utils.DateTimeHelper;
import cn.hengzhu.main_manager.utils.JSONToExcel;
import cn.hengzhu.main_manager.utils.LayUiResultJson;
import cn.hengzhu.main_manager.utils.Md5Util;
import cn.hengzhu.main_manager.utils.UserContext;
import cn.hengzhu.main_manager.utils.WxPayBeforUtil;
import cn.hengzhu.main_manager.utils.ann.MoblieUrl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author liuCheng
 * @since 2018年11月8日 下午6:04:27 公司账单
 */
@Controller
@RequestMapping("/compBill")
public class CompBillController {
	
	private Logger log = Logger.getLogger(CompBillController.class);

	@Autowired
	private PayOrderMapper payordermapper;
	@Autowired
	private ManageCaseMapper manageCaseMapper;
	@Autowired
	private ManageCaseBoxMapper manageCaseBoxMapper;
	@Autowired
	private ManageCompMapper manageCompMapper;
	@Autowired
	private ManageRolesMapper manageRolesMapper;
	@Autowired
	private AccessRecordMapper accessRecordMapper;
	@Autowired
	private HttpServletRequest request;

	@MoblieUrl
	@RequestMapping("/index")
	public String index(Model model) {
		// 查询公司列表
		List<CompVO> list = new ArrayList<>();
		ManageUser user = UserContext.getUser();
		Integer ownCompId = user.getCompId();
		List<ManageComp> manageCompList = new ArrayList<>();
		ManageCompExample example = new ManageCompExample();
		if (ownCompId.equals(0)) {// 查询全部
			manageCompList = manageCompMapper.selectByExample(example);
			manageCompList.stream().forEach(a -> {
				CompVO compVO = new CompVO();
				compVO.setCompId(a.getCompId());
				compVO.setCompName(a.getCompName());
				list.add(compVO);
			});
			CompVO compVO = new CompVO();
			compVO.setCompName("-------请选择--------");
			list.add(0, compVO);

		} else {// 查询自己
			example.createCriteria().andCompIdEqualTo(ownCompId);
			manageCompList = manageCompMapper.selectByExample(example);
			ManageComp manageComp = manageCompList.get(0);
			CompVO compVO = new CompVO();
			compVO.setCompId(ownCompId);
			compVO.setCompName(manageComp.getCompName());
			list.add(compVO);
		}
		model.addAttribute("compList", list);
		return request.getAttribute("moblie") + "compBill";
	}

	/**
	 * @param param
	 * @return 公司账单列表
	 * @throws UnsupportedEncodingException
	 * @author liuCheng
	 * @since 2018年11月9日 上午9:27:46
	 */
	@ResponseBody
	@RequestMapping("/getCompBillList")
	public LayUiResultJson<CompBillVO> getCompBillList(CompBillParam param, HttpServletResponse response,
			Integer excel) {
		System.err.println("param "+param.toString());
		ManageUser user = UserContext.getUser();
		ManageRoles roles = manageRolesMapper.selectByPrimaryKey(user.getRoleId());
		final float percent = roles.getPercent();
		Integer ownCompId = user.getCompId();
		LayUiResultJson<CompBillVO> result = new LayUiResultJson<CompBillVO>();
		CompBillListVO compBillListVO = new CompBillListVO();
		List<CompBillVO> list = new ArrayList<>();
		List<ManageCase> manageCaseList = new ArrayList<>();
		Integer compId = param.getCompId();
		long count = 0;
		long refoundCount = 0;
		String caseNo2 = param.getCaseNo();
		ManageCaseExample manageCaseExample = new ManageCaseExample();
		
		if (null != compId) {
			ownCompId = compId;
		}
		if (StringUtils.isNotBlank(caseNo2)) {
			// 根据caseNo筛选，caseNo不为空，，，那么compId必定不为空
			// 查询公司信息
			System.err.println("caseNo2"+caseNo2.toString());
			ManageComp managecomp = manageCompMapper.selectByPrimaryKey(ownCompId);
			String compName = managecomp.getCompName();
			// 查询储物柜对应的储物箱
			ManageCaseBoxExample manageCaseBoxExample = new ManageCaseBoxExample();
			manageCaseBoxExample.createCriteria().andCaseNoEqualTo(caseNo2);
			List<ManageCaseBox> manageCaseBoxList = manageCaseBoxMapper.selectByExample(manageCaseBoxExample);
			if (!manageCaseBoxList.isEmpty()) {
				List<Integer> caseBoxId = manageCaseBoxList.stream()
						.collect(Collectors.mapping(ManageCaseBox::getId, Collectors.toList()));
				PageHelper.startPage(param.getPage(), param.getLimit(), true);
				param.setBoxIdList(caseBoxId);
				List<PayOrder> payOrderList = payordermapper.getCompBillListByCompId(param);

				PageInfo<PayOrder> pageInfo = new PageInfo<>(payOrderList);
				payOrderList.stream().forEach(a -> {
					CompBillVO compBillVO = new CompBillVO();
					Integer totalFee = a.getTotalFee();
					double doubleValue = totalFee.doubleValue();
					Double money = doubleValue / 100;
					compBillVO.setCompName(compName);
					compBillVO.setCaseNo(caseNo2);
					compBillVO.setOpenId(a.getOpenId());
					compBillVO.setPayAmount((money * percent) + "");
					compBillVO.setPayTime(
							DateTimeHelper.formatDateTimetoString(a.getCreartTime(), "yyyy-MM-dd HH:mm:ss"));
					list.add(compBillVO);
				});
				count = pageInfo.getTotal();
			}
		} else {
			
			
			System.err.println("ownCompId"+ownCompId);
			// 1.查询所选公司的储物柜
			if (ownCompId == 0) {
				manageCaseList = manageCaseMapper.selectByExample(manageCaseExample);
			} else {
				manageCaseExample.createCriteria().andCompIdEqualTo(ownCompId);
				manageCaseList = manageCaseMapper.selectByExample(manageCaseExample);
			}
			List<String> caseNoList = manageCaseList.stream()
					.collect(Collectors.mapping(ManageCase::getCaseNo, Collectors.toList())).stream().distinct()
					.collect(Collectors.toList());
			if (null != caseNoList && !caseNoList.isEmpty()) {
				Map<String, Integer> caseNoToCompIdMap = manageCaseList.stream()
						.collect(Collectors.toMap(ManageCase::getCaseNo, ManageCase::getCompId));
				List<Integer> compIdList = manageCaseList.stream()
						.collect(Collectors.mapping(ManageCase::getCompId, Collectors.toList())).stream().distinct()
						.collect(Collectors.toList());
				// 查询公司
				ManageCompExample manageCompExample = new ManageCompExample();
				manageCompExample.createCriteria().andCompIdIn(compIdList);
				List<ManageComp> manageCompList = manageCompMapper.selectByExample(manageCompExample);
				Map<Integer, String> compIdToCompNameMap = manageCompList.stream()
						.collect(Collectors.toMap(ManageComp::getCompId, ManageComp::getCompName));

				// 2.查询储物柜对应的储物箱
				Map<String, ManageCase> caseNoToMcMap = manageCaseList.stream().collect(Collectors.toMap(ManageCase::getCaseNo, v->v));
				ManageCaseBoxExample manageCaseBoxExample = new ManageCaseBoxExample();
				manageCaseBoxExample.createCriteria().andCaseNoIn(caseNoList);
				List<ManageCaseBox> manageCaseBoxList = manageCaseBoxMapper.selectByExample(manageCaseBoxExample);
				List<Integer> boxIdList = manageCaseBoxList.stream()
						.collect(Collectors.mapping(ManageCaseBox::getId, Collectors.toList()));
				Map<Integer, String> boxIdToCaseNoMap = manageCaseBoxList.stream()
						.collect(Collectors.toMap(ManageCaseBox::getId, ManageCaseBox::getCaseNo));
				
				// 3.查询储物箱对应的账单记录
				if (null != boxIdList && !boxIdList.isEmpty()) {
					PageHelper.startPage(param.getPage(), param.getLimit(), true);
					param.setBoxIdList(boxIdList);
					List<AccessRecord> accessRecordList = accessRecordMapper.getCompBillListByBoxIds(param);
					PageInfo<AccessRecord> pageInfo = new PageInfo<>(accessRecordList);
					accessRecordList.stream().forEach(a -> {
						CompBillVO compBillVO = new CompBillVO();
						Integer boxId = a.getBoxId();
						String caseNo = boxIdToCaseNoMap.get(boxId);
						Integer compId2 = caseNoToCompIdMap.get(caseNo);
						String compName = compIdToCompNameMap.get(compId2);
						String charge = a.getCharge().toString();
						double money = Double.parseDouble(charge);
						double serviceCharge = money;
						if (money > 1) {
							money = Double.parseDouble(String.format("%.2f",money * (1 - 0.006)));
						}
						compBillVO.setCompName(compName);
						compBillVO.setCaseNo(caseNo);
						compBillVO.setOpenId(a.getUserId());
						compBillVO.setSource(a.getSource());
						compBillVO.setServiceCharge(String.format("%.2f", serviceCharge - money));
						compBillVO.setPayAmount(new BigDecimal(money+"").multiply(new BigDecimal(percent+""))+"");
						compBillVO.setPayTime(
								DateTimeHelper.formatDateTimetoString(a.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
						compBillVO.setIsRefund(a.getIsRefund());
						compBillVO.setId(a.getId());
						ManageCase manageCase = caseNoToMcMap.get(caseNo);
						if(manageCase!=null){
							compBillVO.setCaseNoBuy(manageCase.getCaseNoBuy());
							compBillVO.setPlace(manageCase.getPlace());
						}
						list.add(compBillVO);
					});
					count = pageInfo.getTotal();
					AccessRecordExample accessRecordExample = new AccessRecordExample();
					accessRecordExample.createCriteria().andBoxIdIn(boxIdList).andChargeGreaterThan(new BigDecimal("0")).andIsRefundEqualTo(Byte.parseByte("1"));
					refoundCount = accessRecordMapper.countByExample(accessRecordExample);
				}
				compBillListVO.setList(list);
			}

		}

		result.setCount(count);
		result.setMsg(refoundCount+"");
		result.setData(list);
		List<CompBillVO> collect = list.stream().filter(item->Byte.valueOf("0").equals(item.getIsRefund())).collect(Collectors.toList());
		JSONToExcel.excel(collect, request);
		return result;
	}

	@RequestMapping("/excel")
	public void demo(HttpServletResponse response) {
		
		InputStream in = null;
		OutputStream out = null;

		String url = request.getSession().getServletContext().getRealPath("/") + "resources/账单.xls";

		try {

			in = new FileInputStream(url);
			// 创建数据缓冲区
			byte[] buffer = new byte[1024];
			int len = -1;
			// 通过response对象获取outputStream流
			out = response.getOutputStream();
			// 将FileInputStream流写入到buffer缓冲区
			response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("账单.xls", "utf-8"));
			while ((len = in.read(buffer)) != -1) {
				// 使用OutputStream将缓冲区的数据输出到浏览器
				out.write(buffer, 0, len);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				out.close();
				in.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 账单记录-退款
	 * @param recordId 账单记录ID
	 * @param password 管理员登录密码
	 * @return
	 */
	@ResponseBody
	@RequestMapping("/refund")
	public AjaxResult refund(Integer recordId,String password) {
		ManageUser loginUser = (ManageUser)SecurityUtils.getSubject().getPrincipal();
		if(!loginUser.getPassWord().equals(Md5Util.hash(password)))
			return new AjaxResult("密码错误,退款失败");
		
		AccessRecord accessRecord = accessRecordMapper.selectByPrimaryKey(recordId);
		if(accessRecord == null)
			return new AjaxResult("未找到此记录");
		
		PayOrder payOrderByCompBillRecord = payordermapper.getPayOrderByCompBillRecord(accessRecord);
		if(payOrderByCompBillRecord == null)
			return new AjaxResult("未找到此订单");
		
		boolean refundFlag = false;
		Byte source = accessRecord.getSource();
		String transactionId = payOrderByCompBillRecord.getTransactionId();//订单号
		Integer totalFee = payOrderByCompBillRecord.getTotalFee()+(payOrderByCompBillRecord.getPayPledge().multiply(new BigDecimal(100)).intValue());//收款总金额 单位为 分
		BigDecimal refundFee = accessRecord.getCharge();// 收款金额单位为 元 //实际退款金额
		//TODO 微信
		if(Byte.valueOf("2").equals(source) || Byte.valueOf("3").equals(source)){
			try {
				Double doubleValue = refundFee.doubleValue() * 100;//转为分
				log.info("[微信]退款信息：transaction_id:" + transactionId + " totalFee:" + totalFee + "分  refundFee:"+ doubleValue.intValue()+"分");
				Map<String, String> wxRefundMap = WxPayBeforUtil.wxRefund(transactionId,totalFee, doubleValue.intValue());
				log.info(wxRefundMap.toString());
				String resultCode = wxRefundMap.get("result_code");
				if(StringUtils.isNotBlank(resultCode) && resultCode.equals("SUCCESS")) {// 退款申请成功
					log.info("微信退款成功");
					refundFlag = true;
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				return new AjaxResult("退款异常");
			}
		//TODO 支付宝
		}else if(Byte.valueOf("4").equals(source) || Byte.valueOf("5").equals(source)){
			try {
				log.info("[支付宝]退款信息：transaction_id:" + transactionId + " refundFee:"+ refundFee+"元");
				AlipayTradeRefundResponse aliRefund = WxPayBeforUtil.aliRefund(transactionId,refundFee);
				log.info(aliRefund.getSubMsg()+"    "+aliRefund.getMsg());
				if (aliRefund.isSuccess()) {
					log.info("支付宝退款成功");
					refundFlag = true;
				}
			} catch (AlipayApiException e) {
				// TODO Auto-generated catch block
				return new AjaxResult("退款异常");
			}
		}
		if(refundFlag){
			accessRecord.setIsRefund((byte)1);
			int updateByPrimaryKey = accessRecordMapper.updateByPrimaryKeySelective(accessRecord);
			if(updateByPrimaryKey > 0){
				return new AjaxResult();
			}
			log.error("退款正常,修改支付记录失败[记录ID]："+accessRecord.getId());
			return new AjaxResult("退款正常,修改支付记录失败");
		}
		return new AjaxResult("退款失败");
	}
	
	
	
}
